/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/*
 * MainUI.java
 *
 * Created on Sep 23, 2011, 6:37:25 PM
 */
package sdc;

import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import javax.swing.DefaultListModel;
import javax.swing.SwingUtilities;
import java.io.*;
import java.net.URI;
import java.util.Properties;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPopupMenu;
import javax.swing.ListSelectionModel;

/**
 *
 * @author Don
 */
public class MainUI extends javax.swing.JFrame implements ScraperMessageReceiver {

    private Properties properties;
    private Scraper scraper;
    private PostRenderer postRenderer = new PostRenderer();
    private DefaultListModel listModel = new DefaultListModel();
    
    /** Creates new form MainUI */
    public MainUI() {
        initComponents();
        // Create the scraper
        this.scraper = new Scraper(this);
        // Load settings
        this.loadSettings();
        // Set the list renderer
        this.jlstMain.setCellRenderer(this.postRenderer);
        this.jlstMain.setModel(this.listModel);
        this.jlstMain.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        this.jlstMain.setSelectionModel(new PostListSelectionModel());
        // start the scraper
        this.scraper.start();
    }
    
    @Override
    public void receivePost(final Post post) {
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                while (listModel.size() > 50) {
                    listModel.remove(listModel.size() - 1);
                }
                if (jlstMain.getSelectedIndex() == 0) {
                    jlstMain.removeSelectionInterval(0, 0);
                    listModel.add(0, post);
                    jlstMain.setSelectedIndex(1);
                }
                else {
                    listModel.add(0, post);
                }
                jlstMain.ensureIndexIsVisible(jlstMain.getSelectedIndex());
            }
        });
    }
    
    @Override
    public void statusUpdate(final String status) {
        final int width = this.getWidth();
        SwingUtilities.invokeLater(new Runnable(){
            public void run(){
                jlblStatus.setText(status);
            }
        });
    }
    
    /** Gets the users settings */
    public void loadSettings() {
        try {
            // Get the settings dir
            File settingsDir = this.getSettingsDirectory();
            // Get the properties file
            File propertiesFile = new File(settingsDir, "slickdealscrawler.properties");
            // Create the properties file if it doesn't exist
            if (!propertiesFile.exists()) {
                this.createResource(propertiesFile, "/resources/slickdealscrawler.properties");
            }
            // Load the properties file
            FileInputStream in = new FileInputStream(propertiesFile);
            this.properties = new Properties();
            this.properties.load(in);
            in.close();
            // Set the current settings
            this.scraper.setURL(this.properties.getProperty("url"));
        }
        catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
        catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /** Gets the users settings */
    public void saveSettings() {
        try {
            // Get the settings dir
            File settingsDir = this.getSettingsDirectory();
            // Get the properties file
            File propertiesFile = new File(settingsDir, "slickdealscrawler.properties");
            // Write out the properties
            FileOutputStream out = new FileOutputStream(propertiesFile);
            this.properties.store(out, "---No Comment---");
            out.close();
        }
        catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
        catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
    }

    
    /** Writes a file from the manifest to the disk */
    public void createResource(File file, String resource) {
        try {
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            BufferedInputStream bis = new BufferedInputStream(this.getClass().getResourceAsStream(resource));
            byte[] bytes = new byte[1024];
            while (bis.available() > 0) {
                int bytesRead = bis.read(bytes);
                fos.write(bytes, 0, bytesRead);
            }
            bis.close();
            fos.close();
        }
        catch (FileNotFoundException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
        catch (IOException ex) {
            JOptionPane.showMessageDialog(null, "Unknown exception: " + ex.toString(), "Exception", JOptionPane.ERROR_MESSAGE);
        }
    }
    
    /** Gets the users home directory */
    private File getSettingsDirectory() {
        String userHome = System.getProperty("user.home");
        if(userHome == null) {
            throw new IllegalStateException("user.home==null");
        }
        File home = new File(userHome);
        File settingsDirectory = new File(home, ".sdc");
        if(!settingsDirectory.exists()) {
            if(!settingsDirectory.mkdir()) {
                throw new IllegalStateException(settingsDirectory.toString());
            }
        }
        return settingsDirectory;
    }



    /** This method is called from within the constructor to
     * initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is
     * always regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jspMain = new javax.swing.JScrollPane();
        jlstMain = new javax.swing.JList();
        jpnlStatus = new javax.swing.JPanel();
        jlblStatus = new javax.swing.JLabel();
        jmnbMain = new javax.swing.JMenuBar();
        jmnuFile = new javax.swing.JMenu();
        jmiExit = new javax.swing.JMenuItem();
        jmnuOptions = new javax.swing.JMenu();
        jmniSetURL = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Slickdeals Thread Crawler");
        setBounds(new java.awt.Rectangle(0, 0, 0, 0));
        setLocationByPlatform(true);
        setMinimumSize(new java.awt.Dimension(64, 64));
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jspMain.setBorder(null);
        jspMain.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);
        jspMain.setMinimumSize(new java.awt.Dimension(0, 0));
        jspMain.setPreferredSize(new java.awt.Dimension(400, 600));

        jlstMain.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jlstMain.setAutoscrolls(false);
        jlstMain.setMaximumSize(new java.awt.Dimension(32767, 32767));
        jlstMain.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mousePressed(java.awt.event.MouseEvent evt) {
                jlstMainMousePressed(evt);
            }
        });
        jspMain.setViewportView(jlstMain);

        getContentPane().add(jspMain, java.awt.BorderLayout.CENTER);

        jpnlStatus.setBorder(javax.swing.BorderFactory.createEtchedBorder());
        jpnlStatus.setMinimumSize(new java.awt.Dimension(10, 28));
        jpnlStatus.setPreferredSize(new java.awt.Dimension(10, 28));
        jpnlStatus.setLayout(new java.awt.FlowLayout(java.awt.FlowLayout.LEFT));

        jlblStatus.setText("Status");
        jpnlStatus.add(jlblStatus);

        getContentPane().add(jpnlStatus, java.awt.BorderLayout.SOUTH);

        jmnuFile.setText("File");

        jmiExit.setText("Exit");
        jmiExit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmiExitActionPerformed(evt);
            }
        });
        jmnuFile.add(jmiExit);

        jmnbMain.add(jmnuFile);

        jmnuOptions.setText("Options");

        jmniSetURL.setText("Set thread URL");
        jmniSetURL.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jmniSetURLActionPerformed(evt);
            }
        });
        jmnuOptions.add(jmniSetURL);

        jmnbMain.add(jmnuOptions);

        setJMenuBar(jmnbMain);

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void jmiExitActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmiExitActionPerformed
    System.exit(0);
}//GEN-LAST:event_jmiExitActionPerformed

private void jmniSetURLActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jmniSetURLActionPerformed
    String newURL = JOptionPane.showInputDialog("Please give me the desired URL", this.scraper.getURL());
    if (newURL != null && !newURL.equals("")) {
        this.scraper.setURL(newURL);
        this.scraper.start();
    }
}//GEN-LAST:event_jmniSetURLActionPerformed

private void formWindowClosing(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_formWindowClosing
    this.properties.setProperty("url", this.scraper.getURL());
    this.saveSettings();
}//GEN-LAST:event_formWindowClosing

private void jlstMainMousePressed(java.awt.event.MouseEvent evt) {//GEN-FIRST:event_jlstMainMousePressed
    // Select the cell with a right click
    if (evt.getButton() == MouseEvent.BUTTON3) {
        int index = this.jlstMain.locationToIndex(evt.getPoint());
        this.jlstMain.setSelectedIndex(index);
    }
    // Create a pop up menu
    if (SwingUtilities.isRightMouseButton(evt)) {
        final String postURL = ((Post)jlstMain.getSelectedValue()).getPostURL();
        JPopupMenu contextMenu = new JPopupMenu();
        JMenuItem viewPost = new JMenuItem("View Post");
        viewPost.addActionListener(new ActionListener(){
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                try {
                    java.awt.Desktop.getDesktop().browse(new URI(postURL));
                }
                catch (Exception ignore) {}
            }
        });
        contextMenu.add(viewPost);
        contextMenu.show(evt.getComponent(), evt.getX()+5, evt.getY());
    }
}//GEN-LAST:event_jlstMainMousePressed

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Motif".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException ex) {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        } catch (javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(MainUI.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {

            public void run() {
                new MainUI().setVisible(true);
            }
        });
    }
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel jlblStatus;
    private javax.swing.JList jlstMain;
    private javax.swing.JMenuItem jmiExit;
    private javax.swing.JMenuBar jmnbMain;
    private javax.swing.JMenuItem jmniSetURL;
    private javax.swing.JMenu jmnuFile;
    private javax.swing.JMenu jmnuOptions;
    private javax.swing.JPanel jpnlStatus;
    private javax.swing.JScrollPane jspMain;
    // End of variables declaration//GEN-END:variables
}
